package io.netty.myExample.duyutian.exercise.exerciseOne;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author duyutian
 * @version 1.0
 * @date2020/6/23 14:07
 * 测试原子类
 */
public class ExerciseOneClient {
    private static Selector selector;

    public static void main(String[] args) throws IOException, InterruptedException {
        //创建通道管理器(Selector)
        selector = Selector.open();
        //创建通道SocketChannel
        SocketChannel channel = SocketChannel.open();
        //将通道设置为非阻塞
        channel.configureBlocking(false);
        //客户端连接服务器，其实方法执行并没有实现连接，需要在handleConnect方法中调channel.finishConnect()才能完成连接
        channel.connect(new InetSocketAddress("localhost", 8989));
        /**
         *  *
         *  将通道(Channel)注册到通道管理器(Selector)，并为该通道注册selectionKey.OP_CONNECT
         *  * 注册该事件后，当事件到达的时候，selector.select()会返回，
         *  * 如果事件没有到达selector.select()会一直阻塞。         */
        channel.register(selector, SelectionKey.OP_CONNECT);
        //循环处理
        while (true) {
            // Thread.sleep(1000);
            /**
             *  * 选择一组可以进行I/O操作的事件，放在selector中，客户端的该方法不会阻塞，
             *  * selector的wakeup方法被调用，方法返回，而对于客户端来说，通道一直是被选中的
             *  * 这里和服务端的方法不一样，查看api注释可以知道，当至少一个通道被选中时。
             *  */
            selector.select();
            //获取监听事件
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            int i = 0;
            //迭代处理
            while (iterator.hasNext()) {
                i++;
                //获取事件
                SelectionKey key = iterator.next();
                //检查是否是一个就绪的已经连接服务端成功事件
                if (key.isConnectable()) {
                    handleConnect(key);
                    //移除事件，避免重复处理
                    iterator.remove();
                } else if (key.isReadable()) {
                    // 检查套接字是否已经准备好读数据
                    handleRead(key);

                }
            }
            System.out.println("总长度:" + i);
        }
    }

    /**
     * 处理客户端连接服务端成功事件
     */
    private static void handleConnect(SelectionKey key) throws IOException, InterruptedException {
        //获取与服务端建立连接的通道
        SocketChannel channel = (SocketChannel) key.channel();
        if (channel.isConnectionPending()) {
            channel.finishConnect();
            //才能完成连接
            channel.finishConnect();
        }
        channel.configureBlocking(false);
        //通道注册到选择器，并且这个通道只对读事件感兴趣
        channel.register(selector, SelectionKey.OP_READ);

    }

    /**
     * 监听到读事件，读取客户端发送过来的消息
     */
    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        int total = 0;
        ByteBuffer buffer = ByteBuffer.allocate(1000);
        //取出来就被消费了。
        channel.read(buffer);
        System.out.println("收到来自服务端的msg:" + new String(buffer.array()));

        //数据写入通道
        String msg = "Hello Server!";
        channel.write(ByteBuffer.wrap(msg.getBytes()));
        System.out.println("正在向服务端写:" + msg);
    }
}
